﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.ResourceManagement.ResourceLocations;

public class XDownload : MonoBehaviour
{
    public static string catalogPath
    {
        get
        {
            return UnityEngine.Application.persistentDataPath + "/com.unity.addressables";
        }
    }
    public const string updateLabel = "update";

    private bool _isChecking;
    AsyncOperationHandle<List<string>> _catalogHandle;
    AsyncOperationHandle _downloadHandle;
    private List<string> _catalogs;
    private long downloadSize;

    private async void Start()
    {
        await CheckCatalogAsync(() => {
            Debug.Log("下载完成");
            Facade.Instance.SendEvent(EventID.Download_Finish, null);
        });
    }

    public async Task CheckCatalogAsync(Action checkDoneCallback = null)
    {
        if (_isChecking)
            return;

        Debug.Log("check catalog begin");
        _isChecking = true;

        if (!_catalogHandle.IsValid())
            _catalogHandle = Addressables.CheckForCatalogUpdates(false);
        _catalogs = await _catalogHandle.Task;
        Debug.Log("catalogs:" + _catalogs.Count);
        foreach (var catalog in _catalogs)
        {
            Debug.Log("catalog:" + catalog + " type:" + catalog.GetType());
        }
        if (_catalogs != null && _catalogs.Count > 0)
        {
            Debug.Log("Updatecatalogs begin");
            List<object> keys = new List<object>();

            var assets = await Addressables.UpdateCatalogs(_catalogs).Task;
            for (int i = 0; i < assets.Count; i++)
            {
                keys.AddRange(assets[i].Keys);
            }

            GetKeysFromLabel(updateLabel,async (result, updateKeys) => { 
                if(result == AsyncOperationStatus.Succeeded)
                {
                    foreach (var updateKey in updateKeys)
                    {
                        Debug.Log("下载label=\"update\"的key:" + updateKey);
                    }
                    Debug.Log("check download begin updateKeys:" + updateKeys.Count);
                    await CheckDownloadAsync(updateKeys, checkDoneCallback);
                }
                else
                {
                    foreach (var key in keys)
                    {
                        Debug.Log("下载key:" + key);
                    }
                    Debug.LogError("check download begin keys:" + keys.Count);
                    await CheckDownloadAsync(keys, checkDoneCallback);
                }
            });

        }
        else
        {
            await CheckDoneToGameAsync(checkDoneCallback);
        }
        Addressables.Release(_catalogHandle);
    }

    private async Task CheckDownloadAsync(List<object> keys, Action checkDoneCallback = null)
    {
        IEnumerable keyIEnumerable = keys as IEnumerable;
        if (keyIEnumerable == null)
        {
            Debug.LogError("装逼失败：keyIEnumerable = null");
            return;
        }
        downloadSize = await Addressables.GetDownloadSizeAsync(keyIEnumerable).Task;
        Debug.Log("downloadsize:" + downloadSize);
        if (downloadSize > 0)
        {
            //string title = "更新资源";
            string content = string.Format("资源大小:{0}MB", (Mathf.Ceil((float)downloadSize / (1024 * 1024))).ToString());

            var arg = new ArrayList();
            arg.Add(content);
            Action actionOk = async () =>
            {
                await DownloadAsync(keys, checkDoneCallback);
            };
            arg.Add(actionOk);
            Action actionCancel = () =>
            {
                _isChecking = false;
                //自己决定不更新，能不能进游戏:这是临时代码
#if UNITY_EDITOR
                UnityEditor.EditorApplication.isPlaying = false;
#else
                Application.Quit();
#endif
            };
            arg.Add(actionCancel);
            Facade.Instance.SendEvent(EventID.Download_Ask, arg);
        }
        else
        {
            await CheckDoneToGameAsync(checkDoneCallback);
        }
    }

    private async Task DownloadAsync(List<object> keys, Action checkDoneCallback = null)
    {
        Debug.Log("dowload begin");
        IEnumerable keyIEnumerable = keys as IEnumerable;
        if (keyIEnumerable == null)
        {
            Debug.LogError("装逼失败：keyIEnumerable = null");
            return;
        }
        _downloadHandle = Addressables.DownloadDependenciesAsync(keyIEnumerable, Addressables.MergeMode.Union);
        while (!_downloadHandle.IsDone)
        {
            Facade.Instance.SendEvent(EventID.Download_Progress, _downloadHandle.GetDownloadStatus().Percent);
            await Task.Delay(TimeSpan.FromSeconds(Time.deltaTime));
        }
        Debug.Log("download finish");

        if (_downloadHandle.Status == AsyncOperationStatus.Succeeded)
        {
            Debug.Log("download success!");
            //Addressables.Release(_catalogHandle);
            Addressables.Release(_downloadHandle);
            await CheckDoneToGameAsync(checkDoneCallback);
        }
        else
        {
            Debug.LogError("继续尝试下载(需要弄成UI提醒玩家下载)：download failed! error:" + _downloadHandle.OperationException.ToString());
           // await DownloadAsync(keys, checkDoneCallback);

            string content = string.Format("下载失败，重新下载。资源大小:{0}", (Mathf.Ceil((float)downloadSize / (1024 * 1024))).ToString());


            var arg = new ArrayList();
            arg.Add(content);
            Action actionOk = async () =>
            {
                await DownloadAsync(keys, checkDoneCallback);
            };
            arg.Add(actionOk);
            Action actionCancel = () =>
            {
                _isChecking = false;
                //自己决定不更新，能不能进游戏:这是临时代码
#if UNITY_EDITOR
                UnityEditor.EditorApplication.isPlaying = false;
#else
                Application.Quit();
#endif
            };
            arg.Add(actionCancel);
            Facade.Instance.SendEvent(EventID.Download_Ask, arg);
        }
    }

    private async Task CheckDoneToGameAsync(Action checkDoneCallback)
    {
        await Task.Delay(TimeSpan.FromSeconds(Time.deltaTime));
        checkDoneCallback?.Invoke();
        //把脚本删除
        GameObject.Destroy(this);
    }

    public static async void GetKeysFromLabel(string label, Action<AsyncOperationStatus, List<object>> callBack)
    {
        Debug.Log("[aa]【通过Labels获取Keys】");
        DateTime startTime = DateTime.Now;
        AsyncOperationHandle<IList<IResourceLocation>> handle = Addressables.LoadResourceLocationsAsync((new List<string>() { label }) as IEnumerable, Addressables.MergeMode.Union);
        await handle.Task;
        if (handle.Status == AsyncOperationStatus.Succeeded)
        {
            Debug.Log(string.Format("[aa]【通过Labels获取Keys成功】数量：{0} 用时：{1:0.00}S", handle.Result.Count, (DateTime.Now - startTime).Seconds));
            List<object> keys = new List<object>();
            foreach (var item in handle.Result)
            {
                keys.Add(item.PrimaryKey);
            }
            callBack(AsyncOperationStatus.Succeeded, keys);
        }
        else
        {
            UnityEngine.Debug.LogError(string.Format("[aa]【过Labels获取Keys失败】 用时：{0:0.00}S", (DateTime.Now - startTime).Seconds));
            callBack(AsyncOperationStatus.Failed, null);
        }
        Addressables.Release(handle);
    }
}
